﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web.UI;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;

namespace JQueryControlToolkit
{
    public class JSFunctionConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            return new JSFunctionString((string)value);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(JSFunctionString) || destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(JSFunctionString))
            {
                return new JSFunctionString(value as string);
            }

            if (destinationType == typeof(InstanceDescriptor))
            {
                return new InstanceDescriptor(typeof(JSFunctionString).GetConstructor(new Type[] { typeof(string) }), new object[] { ((JSFunctionString)value).String });
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

    [PersistChildren(false)]
    [ParseChildren(true, "String")]
    [TypeConverter(typeof(JSFunctionConverter))]
    public class JSFunctionString : JSObject
    {
        private string functionString;

        public JSFunctionString()
        {
            functionString = string.Empty;
        }

        public JSFunctionString(string functionString)
        {
            if (string.IsNullOrEmpty(functionString))
                throw new ArgumentNullException("functionString");
            this.functionString = functionString;
        }

        public string ToScript()
        {
            return functionString;
        }

        public void ToScript(TextWriter toScript)
        {
            toScript.Write(functionString);
        }

        public string String
        {
            get { return functionString; }
            set { functionString = value; }
        }
    }



    public class JSFunction : JSObject
    {
        public JSFunction(params JSObject[] statements)
        {
            if (statements == null)
                Body = new JSList();
            else
                Body = new JSList(statements);
            Parameters = new List<string>();
        }

        public List<string> Parameters { get; set; }

        public JSList Body { get; set; }

        #region JSObject Members

        public string ToScript()
        {
            return Extensions.ToScript(this);
        }

        public void ToScript(TextWriter toScript)
        {
            toScript.Write("function(");
            bool isFirst = true;
            foreach (string parameterName in Parameters)
            {
                if (isFirst)
                    isFirst = false;
                else
                    toScript.Write(",");
                toScript.Write(parameterName);
            }
            toScript.Write("){");
            isFirst = true;
            foreach (JSObject statement in Body)
            {
                if (isFirst)
                    isFirst = false;
                else
                    toScript.WriteLine(";");
                statement.ToScript(toScript);
            }
            toScript.Write("}");
        }

        #endregion
    }
}
